﻿using ARSoft.Tools.Net.Dns;
using DomainNameServer;
using DomainNameServer.Models;
using DSVISUAL.LocalDNS.Views;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TinyUtil;

namespace DSVISUAL.LocalDNS
{
    public partial class DomainManagementForm : Form
    {
        public DomainManagementForm()
        {
            InitializeComponent();
            var domains = DomainManager.Instance.DataSource;
            this.listBox1.DataSource = domains;
            listBox1.ItemHeight = listBox1.ItemHeight * 2;
            this.listBox1.SelectedIndexChanged += ListBox1_SelectedIndexChanged;
            this.listBox1.MouseUp += ListBox1_MouseUp;
            listView1.SelectedIndexChanged += ListView1_SelectedIndexChanged;
            listView1.Columns.AddRange(new ColumnHeader[] {
                new ColumnHeader() { Text="Type",Width=50,Name="RecordType" },
                 new ColumnHeader() { Text="Host",Width=120,Name="Host" },
                  new ColumnHeader() { Text="To",Width=150,Name="ResoluteTo" },
                  new ColumnHeader() { Text="Enabled",Width=100,Name= "Enabled"},
            });
            listView1.FullRowSelect = true;
            //this.Shown += DomainManagementForm_Shown;
            this.comboBox1.DataSource = EnumUtil.EnumToBindingList<RecordType>();
            this.StartPosition = FormStartPosition.CenterParent;
            ListBox1_SelectedIndexChanged(null, null);
        }

        private void ListBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                int posindex = listBox1.IndexFromPoint(new Point(e.X, e.Y));
                listBox1.ContextMenuStrip = null;
                if (posindex >= 0 && posindex < listBox1.Items.Count)
                {
                    listBox1.SelectedIndex = posindex;
                    contextMenuStrip1.Items[0].Enabled = true;
                    contextMenuStrip1.Items[2].Enabled = true;
                }
                else
                {
                    contextMenuStrip1.Items[0].Enabled = false;
                    contextMenuStrip1.Items[2].Enabled = false;
                }
                contextMenuStrip1.Show(listBox1, new Point(e.X, e.Y));
            }
            listBox1.Refresh();
        }

        private void ListView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listView1.SelectedItems)
            {
                var info = (item.Tag as ListViewItemData).Trackable;
                SetEditorValue((this.listView1.Tag as DomainInfo), info);
                return;
            }
            this.panelEditor.Visible = false;
        }

        private void SetEditorValue(DomainInfo domain, Trackable d)
        {
            var info = d.Entity as RecordInfo;
            this.checkBox1.DataBindings.Clear();
            this.textBox1.DataBindings.Clear();
            this.textBox2.DataBindings.Clear();
            this.comboBox1.DataBindings.Clear();
            this.label4.DataBindings.Clear();
            this.checkBox1.DataBindings.Add("Checked", info, "Enabled");
            this.textBox1.DataBindings.Add("Text", info, "Host");
            this.textBox2.DataBindings.Add("Text", info, "ResoluteTo");
            this.comboBox1.DataBindings.Add("SelectedItem", info, "RecordType");
            this.label4.DataBindings.Add("Text", domain, "Domain");
            //this.checkBox1.Checked = info.Enabled;
            //this.textBox1.Text = info.Host;
            //this.textBox2.Text = info.ResoluteTo;
            //this.comboBox1.SelectedItem = info.RecordType;
            //this.label4.Text = domain.Domain;
            this.panelEditor.Tag = d;
            this.panelEditor.Visible = true;
        }

        private void GetEditorValue()
        {
            var type = (RecordType)this.comboBox1.SelectedItem;
            if (type != RecordType.A && type != RecordType.Aaaa && type != RecordType.CName)
            {
                MessageBox.Show("Only record type \"A\" and \"Aaaa\" and \"CNAME\" is supported.");
                return;
            }
            var t = this.panelEditor.Tag as Trackable;
            t.SaveChanges();
            MessageBox.Show("Operation Successful");
        }

        private void DomainManagementForm_Shown(object sender, EventArgs e)
        {
            ListBox1_SelectedIndexChanged(null, null);
        }

        private void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var info = this.listBox1.SelectedItem as DomainInfo;
            if (info == null)
                return;
            if (this.listBox1.SelectedIndex == 0)
            {

            }
            BindListView(info);
        }

        private void BindListView(DomainInfo info)
        {
            if (listView1.Tag != null && ReferenceEquals((listView1.Tag as DomainInfo), info))
            {
                return;
            }
            listView1.Tag = info;
            listView1.Items.Clear();
            foreach (var item in info.RecordList)
            {
                var trackable = listView1.AddItem(item, EntityState.Unchanged);
                trackable.SaveHandler += Trackable_SaveHandler;
            }
            this.panelEditor.Hide();
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var idxs = this.listBox1.SelectedIndices;
            var idx_sorted = new List<int>();
            foreach (int idx in idxs)
            {
                idx_sorted.Add(idx);
            }
            foreach (var item in idx_sorted.OrderByDescending(x => x))
            {
                var domain = this.listBox1.Items[item] as DomainInfo;
                if ((listView1.Tag as DomainInfo).Equals(domain))
                {
                    listView1.Items.Clear();
                }
                DomainManager.Instance.RemoveAt(item);
            }
        }

        private void enableDisableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var info = this.listBox1.SelectedItem as DomainInfo;
            if (info != null)
            {
                if (!info.Enabled)
                    DomainManager.Instance.EnableDomain(info.Domain);
                else
                    DomainManager.Instance.DisableDomain(info.Domain);
            }
            //var domains = DomainManager.Instance.DomainList;
            //this.listBox1.DataSource = domains;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //save
            GetEditorValue();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //cancel
            this.panelEditor.Visible = false;
            var t = this.panelEditor.Tag as Trackable;
            if (t.State == EntityState.Added)
            {
                t.State = EntityState.Deleted;
                t.SaveChanges();
            }
        }

        private void enableDisableToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count == 0)
            {
                return;
            }
            foreach (ListViewItem item in this.listView1.SelectedItems)
            {
                var r = (item.Tag as ListViewItemData).Data as RecordInfo;
                r.Enabled = !r.Enabled;
                (item.Tag as ListViewItemData).Trackable.SaveChanges();
            }
            //var app = StorageService.Instance.GetData<AppData>();
            //app.DomainList = DomainManager.Instance.GetDomains();
            //StorageService.Instance.SaveData(app);
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count == 0)
            {
                return;
            }
            var removeList = new List<Trackable>();
            foreach (ListViewItem item in this.listView1.SelectedItems)
            {
                var d = item.Tag as ListViewItemData;
                d.Trackable.State = EntityState.Deleted;
                removeList.Add(d.Trackable);
                this.listView1.Items.Remove(item);
            }
            foreach (var item in removeList)
            {
                item.SaveChanges(removeList.Last() == item);
            }
        }

        private void addNewNToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            //new
            var value = new RecordInfo();
            value.RecordType = RecordType.A;
            value.Enabled = true;
            value.ResoluteTo = "127.0.0.1";
            value.Host = "@";
            var trackable = listView1.AddItem(value, EntityState.Added);
            trackable.SaveHandler += Trackable_SaveHandler;
            listView1.Items[listView1.Items.Count - 1].Selected = true;
            this.SetEditorValue(this.listView1.Tag as DomainInfo, trackable);
        }

        private void Trackable_SaveHandler(object sender, bool e)
        {
            var t = sender as Trackable;
            if (t.State == EntityState.Added)
            {
                var d = this.listView1.Tag as DomainInfo;
                d.RecordList.Add(t.Entity as RecordInfo);
                t.State = EntityState.Unchanged;
                if (e)
                {
                    var appData = StorageService.Instance.GetData<AppData>();
                    appData.DomainList = DomainManager.Instance.GetDomains();
                    StorageService.Instance.SaveData(appData);
                }
            }
            else if (t.State == EntityState.Deleted)
            {
                var d = this.listView1.Tag as DomainInfo;
                d.RecordList.Remove(t.Entity as RecordInfo);
                if (e)
                {
                    var appData = StorageService.Instance.GetData<AppData>();
                    appData.DomainList = DomainManager.Instance.GetDomains();
                    StorageService.Instance.SaveData(appData);
                }
            }
            else if (t.State == EntityState.Modified)
            {
                if (e)
                {
                    var appData = StorageService.Instance.GetData<AppData>();
                    appData.DomainList = DomainManager.Instance.GetDomains();
                    StorageService.Instance.SaveData(appData);
                }
            }
        }

        private void addNewNToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var r = new AddDomainForm().ShowDialogAsAcceptable(new AcceptFormOption());
            if (r == DialogResult.OK)
            {
                ListBox1_SelectedIndexChanged(null, null);
            }
        }

        private void deleteAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Sure DELETE All Items?", "WARNING", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                var removeList = new List<Trackable>();
                foreach (ListViewItem item in this.listView1.Items)
                {
                    var d = item.Tag as ListViewItemData;
                    d.Trackable.State = EntityState.Deleted;
                    removeList.Add(d.Trackable);
                    this.listView1.Items.Remove(item);
                }
                foreach (var item in removeList)
                {
                    item.SaveChanges(true);
                }
            }
        }

        private void importFromHostsFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new HostsImportForm().ShowDialogAsAcceptable(this);

        }

        private void deleteAllToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Sure DELETE All Items?", "WARNING", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                var removeList = new List<DomainInfo>();
                foreach (DomainInfo item in this.listBox1.Items)
                {
                    if ((listView1.Tag as DomainInfo).Equals(item))
                    {
                        listView1.Items.Clear();
                    }
                    removeList.Add(item);
                }
                DomainManager.Instance.RemoveAll();
            }
        }

        private void contextMenuStrip2_Opening(object sender, CancelEventArgs e)
        {
            var disabled = this.listView1.Tag == null;
            this.contextMenuStrip2.Enabled = !disabled;
        }
    }
}
